package org.hxzon.cyclone.pfgen;

import org.hxzon.cyclone.Particle;
import org.hxzon.cyclone.Util;
import org.hxzon.cyclone.Vector3;

//伪弹簧力发生器，硬质弹簧（stiff spring），其中一点固定
public class ParticleFakeSpring implements ParticleForceGenerator {
    //弹簧固定点
    private Vector3 anchor;

    private double springConstant;

    /** Holds the damping on the oscillation of the spring. */
    private double damping;

    public ParticleFakeSpring(Vector3 anchor, double springConstant, double damping) {
        this.anchor = anchor;
        this.springConstant = springConstant;
        this.damping = damping;
    }

    public void updateForce(Particle particle, double duration) {
        if (!particle.hasFiniteMass()) {
            return;
        }

        // 位移向量
        Vector3 position = particle.getPosition().copy();
        position.minusUpdate(anchor);

        // Calculate the constants and check they are in bounds.
        double gamma = 0.5f * Util.realSqrt(4 * springConstant - damping * damping);
        if (gamma == 0.0f) {
            return;
        }
        Vector3 c = position.multi(damping / (2.0f * gamma)).add(particle.getVelocity().multi(1.0f / gamma));

        // Calculate the target position
        Vector3 target = position.multi(Util.realCos(gamma * duration)).add(c.multi(Util.realSin(gamma * duration)));
        target.multi(Util.realExp(-0.5f * duration * damping));

        // 计算加速度
//            Vector3 accel = (target - position) * ((real)1.0 / (duration*duration)) -
//                    particle->getVelocity() * ((real)1.0/duration);
        Vector3 accel = target.minus(position)//
                .multi((double) 1.0 / (duration * duration))//
                .minus(particle.getVelocity().multi((double) 1.0 / duration));
        //从加速度求出力
        particle.addForce(accel.multi(particle.getMass()));
    }

}
